//
// Created by yanhai on 2020/3/28.
//

#include "complex.h"


double imag(const complex &x)
{
    return x.imag();
}

double real(const complex &x)
{
    return x.real();
}

/**
 * 知识点8 返回值传递: return by value   vs   return by reference(to const)
 *        返回值传递：按值传递 vs 按引用传递(const)
 *  返回值类型为引用：要返回的对象在调用这个函数之前就已经是存在的了（要返回的对象不是在这个函数内新产生的）
 *        本函数解释：把第二个参数的值加到第一个参数上，第一个参数本来就是存在的，返回第一个参数时可以选择引用
 *
 *  传递者无需知道接收者是否以reference形式接收：当函数以引用类型返回时，接收者可以使用引用类型接收，也可以使用非引用类型接收。
 *   按值接收：  complex c3 = __doapl(&c1, c2);
 *   按引用接收： complex &c3 = __doapl(&c1, c2);
 *
 *  注：函数名称可以理解为 do assignment plus 的缩写
 *
 * @param ths
 * @param r
 * @return
 */
inline complex &
__doapl(complex *ths, const complex &r)
{
    ths->re += r.re;
    ths->im += r.im;
    return *ths;
}

/**
 * 知识点10 操作符重载-1 成员函数
 * 10.1
 *  用法：
 *    complex c1(2, 1);
 *    complex c2(5);
 *    c2 += c1;
 *
 *  所有的类成员函数都隐藏了一个this指针参数：class complex &complex::operator+=(this, const class complex &r)
 *  被隐藏的this指针不一定是第一个参数，也有可能是最后一个参数，这由编译器决定，这也并不影响我们编程。
 *  上面的 c2 += c1;  c2就是形参this， c1就是形参r
 *  所有的操作符，有2个变量参与的，操作符一定是作用到左边的变量上，左边的变量就是this
 *
 *  c2 += c1; 表示将c1的值加到c2身上，加完就结束了，为什么这个函数要有返回值呢？
 *   针对 c2 += c1; 操作，此函数确实可以不需要返回值；
 *   但是当没有返回值时 c3 += c2 += c1; 这种操作将编译失败。（解释：先将c1的值加到c2身上，在将c2的值加到c3身上）
 *   当没有返回值时，上面的操作可以分解为：c2 += c1;  c3 += void;   因此执行完c2 += c1;后一定要将c2的值返回。
 *   表示为：c2 += c1;  c3 += c2;
 * @param r
 * @return
 */
complex &complex::operator+=(const complex &r)
{
    return __doapl(this, r);
}

std::ostream &operator<<(std::ostream &os, const complex &x)
{
    return os << '(' << real(x) << ',' << imag(x) << ')';
}
